From 29f195383ebbca72030336b70e0698f1c6f70d47 Mon Sep 17 00:00:00 2001 From: "kaf24@labyrinth.cl.cam.ac.uk" Date: Wed, 15 Jan 2003 00:21:24 +0000 Subject: [PATCH] bitkeeper revision 1.15 (3e24a984iRiWWcgfKCxu2p5q3YbxXw) Many files: First half of support for per-domain GDTs and LDTs --- xen-2.4.16/arch/i386/boot/boot.S | 6 +-- xen-2.4.16/arch/i386/entry.S | 5 ++- xen-2.4.16/arch/i386/mm.c | 28 ++++++++++++- xen-2.4.16/arch/i386/process.c | 4 ++ xen-2.4.16/arch/i386/setup.c | 5 ++- xen-2.4.16/arch/i386/traps.c | 5 --- xen-2.4.16/common/domain.c | 8 +++- xen-2.4.16/common/memory.c | 3 ++ xen-2.4.16/include/asm-i386/desc.h | 10 ++--- xen-2.4.16/include/asm-i386/processor.h | 2 +- .../include/hypervisor-ifs/hypervisor-if.h | 39 ++++++++++++------- xen-2.4.16/include/xeno/config.h | 9 +++-- xen-2.4.16/include/xeno/mm.h | 20 ++++++---- xen-2.4.16/include/xeno/sched.h | 16 ++++++++ .../arch/xeno/kernel/process.c | 2 +- .../arch/xeno/kernel/setup.c | 2 +- .../include/asm-xeno/hypervisor.h | 33 ++++++++++++++-- 17 files changed, 145 insertions(+), 52 deletions(-) diff --git a/xen-2.4.16/arch/i386/boot/boot.S b/xen-2.4.16/arch/i386/boot/boot.S index 7c9cff669b..bd62d8ffba 100644 --- a/xen-2.4.16/arch/i386/boot/boot.S +++ b/xen-2.4.16/arch/i386/boot/boot.S @@ -225,11 +225,7 @@ ENTRY(gdt_table) .quad 0x00cff2000000bfff /* 0x2b ring 3 3.95GB data at 0x0 */ .quad 0x00cf9a000000ffff /* 0x30 ring 0 4.00GB code at 0x0 */ .quad 0x00cf92000000ffff /* 0x38 ring 0 4.00GB data at 0x0 */ - .quad 0x0000000000000000 - .quad 0x0000000000000000 - .quad 0x0000000000000000 - .quad 0x0000000000000000 - .fill NR_CPUS*4,8,0 /* space for TSS's and LDT's */ + .fill NR_CPUS,8,0 /* space for TSS's */ # The following adds 12kB to the kernel file size. .org 0x1000 diff --git a/xen-2.4.16/arch/i386/entry.S b/xen-2.4.16/arch/i386/entry.S index ea0a58f75f..910e1f19fc 100644 --- a/xen-2.4.16/arch/i386/entry.S +++ b/xen-2.4.16/arch/i386/entry.S @@ -516,8 +516,8 @@ ENTRY(hypervisor_call_table) .long SYMBOL_NAME(do_set_trap_table) .long SYMBOL_NAME(do_process_page_updates) .long SYMBOL_NAME(do_console_write) - .long SYMBOL_NAME(sys_ni_syscall) - .long SYMBOL_NAME(do_set_guest_stack) + .long SYMBOL_NAME(do_set_gdt) + .long SYMBOL_NAME(do_stack_and_ldt_switch) .long SYMBOL_NAME(do_net_update) .long SYMBOL_NAME(do_fpu_taskswitch) .long SYMBOL_NAME(do_yield) @@ -526,6 +526,7 @@ ENTRY(hypervisor_call_table) .long SYMBOL_NAME(do_network_op) .long SYMBOL_NAME(do_set_debugreg) .long SYMBOL_NAME(do_get_debugreg) + .long SYMBOL_NAME(do_update_descriptor) .rept NR_syscalls-(.-hypervisor_call_table)/4 .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/xen-2.4.16/arch/i386/mm.c b/xen-2.4.16/arch/i386/mm.c index fa62aed4f6..2260882efc 100644 --- a/xen-2.4.16/arch/i386/mm.c +++ b/xen-2.4.16/arch/i386/mm.c @@ -91,7 +91,8 @@ void __init zap_low_mappings (void) } -long do_set_guest_stack(unsigned long ss, unsigned long esp) +long do_stack_and_ldt_switch( + unsigned long ss, unsigned long esp, unsigned long ldts) { int nr = smp_processor_id(); struct tss_struct *t = &init_tss[nr]; @@ -99,6 +100,18 @@ long do_set_guest_stack(unsigned long ss, unsigned long esp) if ( (ss == __HYPERVISOR_CS) || (ss == __HYPERVISOR_DS) ) return -1; + if ( ldts != current->mm.ldt_sel ) + { + unsigned long *ptabent = GET_GDT_ADDRESS(current); + /* Out of range for GDT table? */ + if ( (ldts * 8) > GET_GDT_ENTRIES(current) ) return -1; + ptabent += ldts * 2; /* 8 bytes per desc == 2 * unsigned long */ + /* Not an LDT entry? (S=0b, type =0010b) */ + if ( (*ptabent & 0x00001f00) != 0x00000200 ) return -1; + current->mm.ldt_sel = ldts; + __load_LDT(ldts); + } + current->thread.ss1 = ss; current->thread.esp1 = esp; t->ss1 = ss; @@ -106,3 +119,16 @@ long do_set_guest_stack(unsigned long ss, unsigned long esp) return 0; } + + +long do_set_gdt(unsigned long *frame_list, int entries) +{ + return -ENOSYS; +} + + +long do_update_descriptor( + unsigned long pa, unsigned long word1, unsigned long word2) +{ + return -ENOSYS; +} diff --git a/xen-2.4.16/arch/i386/process.c b/xen-2.4.16/arch/i386/process.c index 11cd5a1c23..c8e81de675 100644 --- a/xen-2.4.16/arch/i386/process.c +++ b/xen-2.4.16/arch/i386/process.c @@ -380,6 +380,10 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs)); asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs)); + /* Switch GDT and LDT. */ + __asm__ __volatile__ ("lgdt %0" : "=m" (*next_p->mm.gdt)); + __load_LDT(next_p->mm.ldt_sel); + /* * Restore %fs and %gs. */ diff --git a/xen-2.4.16/arch/i386/setup.c b/xen-2.4.16/arch/i386/setup.c index e23ca04ea4..a03c4bac4d 100644 --- a/xen-2.4.16/arch/i386/setup.c +++ b/xen-2.4.16/arch/i386/setup.c @@ -194,7 +194,10 @@ void __init cpu_init(void) panic("CPU#%d already initialized!!!\n", nr); printk("Initializing CPU#%d\n", nr); - __asm__ __volatile__("lgdt %0": "=m" (gdt_descr)); + /* Set up GDT and IDT. */ + SET_GDT_ENTRIES(current, DEFAULT_GDT_ENTRIES); + SET_GDT_ADDRESS(current, DEFAULT_GDT_ADDRESS); + __asm__ __volatile__("lgdt %0": "=m" (*current->mm.gdt)); __asm__ __volatile__("lidt %0": "=m" (idt_descr)); /* No nested task. */ diff --git a/xen-2.4.16/arch/i386/traps.c b/xen-2.4.16/arch/i386/traps.c index 85dd1bc93a..0ce294c9f4 100644 --- a/xen-2.4.16/arch/i386/traps.c +++ b/xen-2.4.16/arch/i386/traps.c @@ -514,11 +514,6 @@ void set_tss_desc(unsigned int n, void *addr) _set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 235, 0x89); } -void set_ldt_desc(unsigned int n, void *addr, unsigned int size) -{ - _set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82); -} - void __init trap_init(void) { set_trap_gate(0,÷_error); diff --git a/xen-2.4.16/common/domain.c b/xen-2.4.16/common/domain.c index 90c1a0a779..31ae0b9726 100644 --- a/xen-2.4.16/common/domain.c +++ b/xen-2.4.16/common/domain.c @@ -43,7 +43,10 @@ struct task_struct *do_newdomain(void) if (!p) goto newdomain_out; memset(p, 0, sizeof(*p)); p->shared_info = (void *)get_free_page(GFP_KERNEL); - memset(p->shared_info, 0, sizeof(shared_info_t)); + memset(p->shared_info, 0, PAGE_SIZE); + + SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES); + SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS); p->addr_limit = USER_DS; p->state = TASK_UNINTERRUPTIBLE; @@ -247,6 +250,7 @@ void release_task(struct task_struct *p) { destroy_net_vif(p); } + if ( p->mm.perdomain_pt ) free_page((unsigned long)p->mm.perdomain_pt); free_page((unsigned long)p->shared_info); free_task_struct(p); } @@ -462,6 +466,8 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params) phys_l2tab = ALLOC_FRAME_FROM_DOMAIN(); l2tab = map_domain_mem(phys_l2tab); memcpy(l2tab, idle_pg_table[p->processor], PAGE_SIZE); + l2tab[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] = + mk_l2_pgentry(__pa(p->mm.perdomain_pt) | __PAGE_HYPERVISOR); memset(l2tab, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE*sizeof(l2_pgentry_t)); p->mm.pagetable = mk_pagetable(phys_l2tab); diff --git a/xen-2.4.16/common/memory.c b/xen-2.4.16/common/memory.c index 8cb80c694a..226772ebce 100644 --- a/xen-2.4.16/common/memory.c +++ b/xen-2.4.16/common/memory.c @@ -329,6 +329,9 @@ static int get_l2_table(unsigned long page_nr) memcpy(p_l2_entry, idle_pg_table[smp_processor_id()] + DOMAIN_ENTRIES_PER_L2_PAGETABLE, HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t)); + p_l2_entry[(PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT) - + DOMAIN_ENTRIES_PER_L2_PAGETABLE] = + mk_l2_pgentry(__pa(current->mm.perdomain_pt) | __PAGE_HYPERVISOR); return(ret); } diff --git a/xen-2.4.16/include/asm-i386/desc.h b/xen-2.4.16/include/asm-i386/desc.h index 3855ebcb6c..2cb90769b5 100644 --- a/xen-2.4.16/include/asm-i386/desc.h +++ b/xen-2.4.16/include/asm-i386/desc.h @@ -1,11 +1,8 @@ #ifndef __ARCH_DESC_H #define __ARCH_DESC_H -#define __FIRST_TSS_ENTRY 12 -#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY+1) - -#define __TSS(n) (((n)<<2) + __FIRST_TSS_ENTRY) -#define __LDT(n) (((n)<<2) + __FIRST_LDT_ENTRY) +#define __FIRST_TSS_ENTRY 8 +#define __TSS(n) ((n) + __FIRST_TSS_ENTRY) #ifndef __ASSEMBLY__ struct desc_struct { @@ -25,10 +22,9 @@ struct Xgt_desc_struct { #define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3)) -#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3)) +#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" ((n)<<3)) extern void set_intr_gate(unsigned int irq, void * addr); -extern void set_ldt_desc(unsigned int n, void *addr, unsigned int size); extern void set_tss_desc(unsigned int n, void *addr); #endif /* !__ASSEMBLY__ */ diff --git a/xen-2.4.16/include/asm-i386/processor.h b/xen-2.4.16/include/asm-i386/processor.h index 2e98c53134..b3f496c5bc 100644 --- a/xen-2.4.16/include/asm-i386/processor.h +++ b/xen-2.4.16/include/asm-i386/processor.h @@ -375,7 +375,7 @@ struct thread_struct { 0,0,0,0, /* esp,ebp,esi,edi */ \ 0,0,0,0,0,0, /* es,cs,ss */ \ 0,0,0,0,0,0, /* ds,fs,gs */ \ - __LDT(0),0, /* ldt */ \ + 0,0, /* ldt */ \ 0, INVALID_IO_BITMAP_OFFSET, /* tace, bitmap */ \ {~0, } /* ioperm */ \ } diff --git a/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h b/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h index 1e3705e9ac..226601d62a 100644 --- a/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h +++ b/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h @@ -51,21 +51,34 @@ typedef struct } page_update_request_t; +/* + * Segment descriptor tables. + */ +/* 8 entries, plus a TSS entry for each CPU (up to 32 CPUs). */ +#define FIRST_DOMAIN_GDT_ENTRY 40 +/* These are flat segments for domain bootstrap and fallback. */ +#define FLAT_RING1_CS 0x11 +#define FLAT_RING1_DS 0x19 +#define FLAT_RING3_CS 0x23 +#define FLAT_RING3_DS 0x2b + + /* EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5. */ -#define __HYPERVISOR_set_trap_table 0 -#define __HYPERVISOR_pt_update 1 -#define __HYPERVISOR_console_write 2 -/* vector 3 unused */ -#define __HYPERVISOR_set_guest_stack 4 -#define __HYPERVISOR_net_update 5 -#define __HYPERVISOR_fpu_taskswitch 6 -#define __HYPERVISOR_yield 7 -#define __HYPERVISOR_exit 8 -#define __HYPERVISOR_dom0_op 9 -#define __HYPERVISOR_network_op 10 -#define __HYPERVISOR_set_debugreg 11 -#define __HYPERVISOR_get_debugreg 12 +#define __HYPERVISOR_set_trap_table 0 +#define __HYPERVISOR_pt_update 1 +#define __HYPERVISOR_console_write 2 +#define __HYPERVISOR_set_gdt 3 +#define __HYPERVISOR_stack_and_ldt_switch 4 +#define __HYPERVISOR_net_update 5 +#define __HYPERVISOR_fpu_taskswitch 6 +#define __HYPERVISOR_yield 7 +#define __HYPERVISOR_exit 8 +#define __HYPERVISOR_dom0_op 9 +#define __HYPERVISOR_network_op 10 +#define __HYPERVISOR_set_debugreg 11 +#define __HYPERVISOR_get_debugreg 12 +#define __HYPERVISOR_update_descriptor 13 #define TRAP_INSTR "int $0x82" diff --git a/xen-2.4.16/include/xeno/config.h b/xen-2.4.16/include/xeno/config.h index ccbbd1d325..f139a80066 100644 --- a/xen-2.4.16/include/xeno/config.h +++ b/xen-2.4.16/include/xeno/config.h @@ -41,12 +41,15 @@ #define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES))) #define ____cacheline_aligned __cacheline_aligned -/* 0-16MB is fixed monitor space. 0-56MB is direct-mapped at top of memory.*/ +/* 0-16MB is fixed monitor space. 0-52MB is direct-mapped at top of memory.*/ #define MAX_MONITOR_ADDRESS (16*1024*1024) #define MAX_DMA_ADDRESS (16*1024*1024) -#define MAX_DIRECTMAP_ADDRESS (56*1024*1024) +#define MAX_DIRECTMAP_ADDRESS (52*1024*1024) +/* Next 4MB of virtual address space used for per-domain mappings (eg. GDT). */ +#define PERDOMAIN_VIRT_START (PAGE_OFFSET + MAX_DIRECTMAP_ADDRESS) +#define PERDOMAIN_VIRT_END (PERDOMAIN_VIRT_START + (4*1024*1024)) /* Penultimate 4MB of virtual address space used for domain page mappings. */ -#define MAPCACHE_VIRT_START (PAGE_OFFSET + MAX_DIRECTMAP_ADDRESS) +#define MAPCACHE_VIRT_START (PERDOMAIN_VIRT_END) #define MAPCACHE_VIRT_END (MAPCACHE_VIRT_START + (4*1024*1024)) /* Final 4MB of virtual address space used for ioremap(). */ #define IOREMAP_VIRT_START (MAPCACHE_VIRT_END) diff --git a/xen-2.4.16/include/xeno/mm.h b/xen-2.4.16/include/xeno/mm.h index 93b66c7007..30071e76cf 100644 --- a/xen-2.4.16/include/xeno/mm.h +++ b/xen-2.4.16/include/xeno/mm.h @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -89,13 +90,15 @@ typedef struct pfn_info { * references exist of teh current type. A change in type can only occur * when type_count == 0. */ -#define PG_type_mask (7<<25) /* bits 25-27 */ -#define PGT_none (0<<25) /* no special uses of this page */ -#define PGT_l1_page_table (1<<25) /* using this page as an L1 page table? */ -#define PGT_l2_page_table (2<<25) /* using this page as an L2 page table? */ -#define PGT_l3_page_table (3<<25) /* using this page as an L3 page table? */ -#define PGT_l4_page_table (4<<25) /* using this page as an L4 page table? */ -#define PGT_writeable_page (7<<25) /* has writable mappings of this page? */ +#define PG_type_mask (7<<24) /* bits 24-26 */ +#define PGT_none (0<<24) /* no special uses of this page */ +#define PGT_l1_page_table (1<<24) /* using this page as an L1 page table? */ +#define PGT_l2_page_table (2<<24) /* using this page as an L2 page table? */ +#define PGT_l3_page_table (3<<24) /* using this page as an L3 page table? */ +#define PGT_l4_page_table (4<<24) /* using this page as an L4 page table? */ +#define PGT_gdt_page (5<<24) /* using this page in a GDT? */ +#define PGT_ldt_page (6<<24) /* using this page in an LDT? */ +#define PGT_writeable_page (7<<24) /* has writable mappings of this page? */ #define PageSlab(page) test_bit(PG_slab, &(page)->flags) #define PageSetSlab(page) set_bit(PG_slab, &(page)->flags) @@ -114,4 +117,7 @@ void init_frametable(unsigned long nr_pages); /* Part of the domain API. */ int do_process_page_updates(page_update_request_t *updates, int count); +#define DEFAULT_GDT_ENTRIES ((FIRST_DOMAIN_GDT_ENTRY*8)-1) +#define DEFAULT_GDT_ADDRESS ((unsigned long)gdt_table) + #endif /* __XENO_MM_H__ */ diff --git a/xen-2.4.16/include/xeno/sched.h b/xen-2.4.16/include/xeno/sched.h index 295335bd16..3871faa2f1 100644 --- a/xen-2.4.16/include/xeno/sched.h +++ b/xen-2.4.16/include/xeno/sched.h @@ -19,13 +19,29 @@ extern rwlock_t tasklist_lock; struct mm_struct { unsigned long cpu_vm_mask; + /* + * Every domain has a L1 pagetable of its own. Per-domain mappings + * are put in this table (eg. the current GDT is mapped here). + */ + l2_pgentry_t *perdomain_pt; pagetable_t pagetable; + /* Current LDT selector. */ + unsigned int ldt_sel; + /* Next entry is passed to LGDT on domain switch. */ + char gdt[6]; }; +/* Convenient accessor for mm.gdt. */ +#define SET_GDT_ENTRIES(_p, _e) ((*(u16 *)((_p)->mm.gdt + 0)) = (_e)) +#define SET_GDT_ADDRESS(_p, _a) ((*(u32 *)((_p)->mm.gdt + 2)) = (_a)) +#define GET_GDT_ENTRIES(_p) ((*(u16 *)((_p)->mm.gdt + 0))) +#define GET_GDT_ADDRESS(_p) ((*(u32 *)((_p)->mm.gdt + 2))) + extern struct mm_struct init_mm; #define IDLE0_MM \ { \ cpu_vm_mask: 0, \ + perdomain_pt: 0, \ pagetable: mk_pagetable(__pa(idle0_pg_table)) \ } diff --git a/xenolinux-2.4.16-sparse/arch/xeno/kernel/process.c b/xenolinux-2.4.16-sparse/arch/xeno/kernel/process.c index 9e26f3d65a..1c7f27176d 100644 --- a/xenolinux-2.4.16-sparse/arch/xeno/kernel/process.c +++ b/xenolinux-2.4.16-sparse/arch/xeno/kernel/process.c @@ -337,7 +337,7 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) unlazy_fpu(prev_p); - HYPERVISOR_set_guest_stack(__KERNEL_DS, next->esp0); + HYPERVISOR_stack_and_ldt_switch(__KERNEL_DS, next->esp0, 0); /* * Save away %fs and %gs. No need to save %es and %ds, as diff --git a/xenolinux-2.4.16-sparse/arch/xeno/kernel/setup.c b/xenolinux-2.4.16-sparse/arch/xeno/kernel/setup.c index 082bc31839..2bef924df0 100644 --- a/xenolinux-2.4.16-sparse/arch/xeno/kernel/setup.c +++ b/xenolinux-2.4.16-sparse/arch/xeno/kernel/setup.c @@ -954,7 +954,7 @@ void __init cpu_init (void) BUG(); enter_lazy_tlb(&init_mm, current, nr); - HYPERVISOR_set_guest_stack(__KERNEL_DS, current->thread.esp0); + HYPERVISOR_stack_and_ldt_switch(__KERNEL_DS, current->thread.esp0, 0); /* Force FPU initialization. */ current->flags &= ~PF_USEDFPU; diff --git a/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h b/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h index 839feed153..640c3a958e 100644 --- a/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h +++ b/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h @@ -171,14 +171,26 @@ static inline int HYPERVISOR_console_write(const char *str, int count) return ret; } -static inline int HYPERVISOR_set_guest_stack( - unsigned long ss, unsigned long esp) +static inline int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries) { int ret; __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_set_guest_stack), - "b" (ss), "c" (esp) ); + : "=a" (ret) : "0" (__HYPERVISOR_set_gdt), + "b" (frame_list), "c" (entries) ); + + + return ret; +} + +static inline int HYPERVISOR_stack_and_ldt_switch( + unsigned long ss, unsigned long esp, unsigned long ldts) +{ + int ret; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) : "0" (__HYPERVISOR_stack_and_ldt_switch), + "b" (ss), "c" (esp), "d" (ldts) ); return ret; } @@ -267,4 +279,17 @@ static inline unsigned long HYPERVISOR_get_debugreg(int reg) return ret; } +static inline int HYPERVISOR_update_descriptor( + unsigned long pa, unsigned long word1, unsigned long word2) +{ + int ret; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) : "0" (__HYPERVISOR_set_gdt), + "b" (pa), "c" (word1), "d" (word2) ); + + + return ret; +} + #endif /* __HYPERVISOR_H__ */ -- 2.30.2